using System;
using System.Collections;
using System.Data;
using System.Security.Principal;
using System.Web;
using System.Reflection;

using BEGDC.CC.Entity;
using BEGDC.Utility.Castle;
using BEGDC.CC.BL.UserManagement;

namespace BEGDC.CC.BL.Workflow
{
	/// <summary>
	/// CCPrincipal
	/// </summary>
	public class CCPrincipal : IPrincipal
	{
		private CCIdentity indentity;

		private Hashtable inroles;
        
		/// <summary>
		/// construction function
		/// </summary>
		/// <param name="winPrincipal">CCPrincipal object</param>
        //public CCPrincipal(IPrincipal winPrincipal)
        //{
        //    indentity = new CCIdentity(winPrincipal.Identity);
        //    this.LoadRoles();
        //    this.LoadPermission();
        //}
        public CCPrincipal(IIdentity identity, string[] roles)
        {
            indentity = new CCIdentity(identity);
            //this.LoadRoles();
            //this.LoadPermission();

            IncreaseHashtable(this);
        }

		#region IPrincipal Members

		/// <summary>
		/// Identity object
		/// </summary>
		public IIdentity Identity
		{
			get
			{
				return this.indentity;
			}
		}

		
		/// <summary>
		/// Check user is in role group
		/// </summary>
		/// <param name="role">role list</param>
		/// <returns>true/false</returns>
		public bool IsInRole(string role)
		{
            if (this.inroles == null || this.inroles.Count==0)
                this.LoadRoles();
			string[] roles1 = role.Split('&');
			string[] roles2 = role.Split('|');
			if ((roles1.Length == 1) && (roles2.Length == 1))
			{
				return inroles.ContainsKey(role);
			}
			if (roles1.Length > 1)
			{
				foreach(string r in roles1)
				{
					if (!inroles.ContainsKey(r))
						return false;
				}
				return true;
			}
			if (roles2.Length > 1)
			{
				foreach(string r in roles2)
				{
					if (inroles.ContainsKey(r))
						return true;
				}
				return false;
			}
			return false;
		}

		#endregion

		/// <summary>
		/// Check user is in project role
		/// </summary>
		/// <param name="role">role list</param>
		/// <param name="flowID">workflow id</param>
		/// <returns>true/false</returns>
		public bool IsInRole(string role, long flowID)
		{
			IUser userservice = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UserService] as IUser;
			return userservice.IsInRole(this.indentity.Name, role, flowID);
		}

		//Added by Joe Feng 1/29/2007
		/// <summary>
		/// 
		/// </summary>
		/// <param name="role"></param>
		/// <param name="flowId"></param>
		/// <returns></returns>
		public bool IsInTSRole( string role, long flowId )
		{
			IUser userService = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UserService] as IUser;
			return userService.IsInTSRole( this.indentity.Name, role, flowId );
		}

		/// <summary>
		/// Check user is in project role
		/// </summary>
		/// <param name="role">role list</param>
		/// <param name="projectID">project id</param>
		/// <returns>true/false</returns>
		public bool IsInRole(string role, int projectID)
		{
			IUser userservice = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UserService] as IUser;
			return userservice.IsInRole(this.indentity.Name, role, projectID);
		}

		/// <summary>
		/// Set user's backup
		/// </summary>
		/// <param name="adName">backup's adname</param>
		public void SetBackup(string adName)
		{	
			IUser userservice = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UserService] as IUser;
			Employee user = userservice.GetUser(adName);
			SetBackup(user);
		}

		/// <summary>
		/// Set user's backup
		/// </summary>
		/// <param name="backup">Employee object</param>
		public void SetBackup(Employee backup)
		{	
//			this.ClearCache();
//			HttpContext.Current.Session["BAKIdentity"] = backup;

			this.indentity.Backuper = backup;
			this.LoadRoles();
			this.LoadPermission();
		}

		/// <summary>
		/// Clear user's backup
		/// </summary>
		public void ClearBackup()
		{
			this.indentity.Backuper = null;
			this.LoadRoles();
			this.LoadPermission();
			//HttpContext.Current.Session.Remove("BAKIdentity");
		}

		private bool _isleader = false;

		/// <summary>
		/// if user is leader, the user can see all data.
		/// </summary>
		public bool IsLeader
		{
			get
			{
				return _isleader;
			}
		}

		/// <summary>
		/// reload roles and identity
		/// </summary>
		public void Reload()
		{
			this.LoadRoles();
			this.LoadPermission();
			this.indentity.Reload();

			if (CC_Users.ContainsKey(this.indentity.UserInfo.NameEN))
			{
				CC_Users[this.indentity.UserInfo.NameEN] =  this;
			}
		}

		/// <summary>
		/// no use
		/// </summary>
		private void ClearCache()
		{
//			HttpContext.Current.Session.Remove("Principal");
//			HttpContext.Current.Session.Remove("PrincipalRoles");
//			if (inroles != null)
//			{
//				inroles.Clear();
//				inroles = null;
//			}
			
		}

		private void LoadRoles()
		{
//			/*
//			if ((HttpContext.Current.Session["Principal"] != null) && (HttpContext.Current.Session["PrincipalRoles"] != null))
//			{
//				string name = (string)HttpContext.Current.Session["Principal"];
//				if (name == this.indentity.Name)
//				{
//					inroles = (Hashtable)HttpContext.Current.Session["PrincipalRoles"];
//					if (inroles != null)
//                        return;
//				}
//			}
//			HttpContext.Current.Session["Principal"] = this.indentity.Name;
//			*/
//
			_roles = string.Empty;
			IUser userservice = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UserService] as IUser;

			if (this.Identity == null)
				return;

			if (this.indentity.UserInfo == null)
				return;

            if (HttpContext.Current.Session["AsWho"] != null)
            {
                this.indentity.Backuper = userservice.GetUserByID(
                    HttpContext.Current.Session["AsWho"].ToString());
            }

			if (!((BEGDC.CC.BL.Workflow.CCIdentity)this.Identity).IsBackup)
			{
				_roles = "'" + this.indentity.UserInfo.Id + "',";


				IList roles = userservice.GetRolesByUser(this.indentity.Name);

				inroles = new Hashtable();

				if (roles != null)
				{
					foreach(BEGDC.CC.Entity.Role role in roles)
					{
						if (role.IsEnabled)
						{
                            if (!inroles.ContainsKey(role.RoleName))
                            {
                                inroles.Add(role.RoleName, 0);
                                _roles += "'" + role.RoleName + "',";
                                if (role.IsLeader) this._isleader = true;
                            }
						}
						
					}
					_roles = _roles.TrimEnd(',');
				}
			}
			else
			{
				_roles = "'" + this.indentity.UserInfo.Id + "',";

				IList roles = userservice.GetDelegationUserRoleListByUserID(this.indentity.UserInfo.Id,((BEGDC.CC.BL.Workflow.CCIdentity)this.Identity).ActualUserInfo.Id);

				inroles = new Hashtable();

				if (roles != null)
				{
					foreach(BEGDC.CC.Entity.UserRole role in roles)
					{
						if (role.IsEnabled)
						{
                            inroles.Add(role.Role.RoleName, 0);
							_roles += "'" + role.Role.RoleName + "',";
							if (role.Role.IsLeader)	this._isleader = true;
						}
						
					}
					_roles = _roles.TrimEnd(',');

				}
			}
//			//HttpContext.Current.Session["PrincipalRoles"] = inroles;
		}

		private void LoadPermission()
		{
			_permission = string.Empty;
			_allpermission = string.Empty;

			if (this.Roles == string.Empty)	return;

			IUser iuser = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UserService] as IUser;
			
			System.Data.DataTable dtPermission = iuser.GetPermissionByRole(this.Roles);

			foreach(System.Data.DataRow dr in dtPermission.Rows)
			{
				if (dr["FunctionURL"] != System.DBNull.Value)
					_permission += dr["FunctionURL"].ToString() + ";";
			}

			System.Data.DataTable dtFunction = iuser.GetFunctions();
			foreach(System.Data.DataRow dr in dtFunction.Rows)
			{
				if (dr["FunctionURL"] != System.DBNull.Value)
					_allpermission += dr["FunctionURL"].ToString() + ";";
			}
			_permission = _permission.ToLower();
			_allpermission = _allpermission.ToLower();
		}

		private string _roles = string.Empty;
		public string Roles
		{
			get
			{
                if (string.IsNullOrEmpty(_roles))
                {
                    LoadRoles();
                }
				return _roles;
			}
		}

		private string _permission = string.Empty;
		private string _allpermission = string.Empty;
		
		private static Hashtable CC_Users = new Hashtable();

		public bool IsAccess(string pagename)
		{
            if (string.IsNullOrEmpty(_permission) || string.IsNullOrEmpty(_allpermission))
                LoadPermission();
			bool ret = true;
			if (this._allpermission.IndexOf(pagename.ToLower()) > -1 &&  (this._permission.IndexOf(pagename.ToLower()) == -1))
			{
				ret = false;
			}
			return ret;
		}
		/// <summary>
		/// Get prinicpal
		/// </summary>
		/// <param name="winPrincipal">principal</param>
		/// <returns>CCPrincipal object</returns>
        //public static CCPrincipal GetPrincipal(IPrincipal winPrincipal)
        //{
        //    lock(typeof(CCPrincipal))
        //    {
        //        string adname = winPrincipal.Identity.Name.ToLower();

        //        if (CC_Users.ContainsKey(adname))
        //        {
        //            CCPrincipal re_prin = (CCPrincipal)CC_Users[adname];
        //            if (re_prin.Identity.IsAuthenticated)
        //            {
        //                return re_prin;
        //            }
        //            else
        //                CC_Users.Remove(adname);
        //        }

        //        CCPrincipal principal = new CCPrincipal(winPrincipal);

        //        CC_Users.Add(adname, principal);

        //        return principal;
        //    }
        //}
        private static void IncreaseHashtable(CCPrincipal user)
        {
            lock (typeof(CCPrincipal))
            {
                string adname = user.Identity.Name.ToLower();

                if (CC_Users.ContainsKey(adname))
                {
                    CCPrincipal re_prin = (CCPrincipal)CC_Users[adname];
                    if (re_prin.Identity.IsAuthenticated)
                    {
                        return;
                    }
                    else
                        CC_Users.Remove(adname);
                }

                //CCPrincipal principal = new CCPrincipal(winPrincipal);

                CC_Users.Add(adname, user);
            }
        }

		/// <summary>
		/// Remove principal by adname
		/// </summary>
		/// <param name="adName">adname</param>
		public static void RemovePrincipal(string adName)
		{
			if (adName == null)	return;
			lock(typeof(CCPrincipal))
			{
				if (CC_Users.ContainsKey(adName.ToLower()))
					CC_Users.Remove(adName.ToLower());
			}
		}

		/// <summary>
		/// clear all Principal
		/// </summary>
		/// <param name="adName">adname</param>
		public static void ClearPrincipal()
		{
			lock(typeof(CCPrincipal))
			{
				CC_Users.Clear();
			}
		}
	}
}
